package org.bbelovic.devel.snake;

import java.awt.Color;
import java.awt.Graphics;

public class DefaultGameController {

    private final Snake snake;
    private final int panelWidth;
    private final int panelHeight;
    private final CircleGenerator generator;

    public DefaultGameController(final GameContext ctx) {
        this.snake = ctx.getSnake();
        this.panelWidth = ctx.getPanelWidth();
        this.panelHeight = ctx.getPanelHeight();
        this.generator = ctx.getCircleGenerator();
    }

    /**
     * Paints game scene with {@link Snake} and all other necessary instances
     * @param g {@link Graphics} instance which handles painting
     */
    public void paintGameScene(final Graphics g) {
        snake.drawSnake(g);
        generator.drawCircle(g);
    }

    /**
     * Check whether snake has collided with window border.
     * @return true if snake has collided with window border, false otherwise
     */
    public boolean isInBorderCollision() {
        boolean result = false;
        final int circleSize = Snake.getSnakesCircleSize();
        if (snake.getX() < 0 || snake.getY() < 0) {
            result = true;
        }
        if (snake.getX() + circleSize > panelWidth || snake.getY() + circleSize > panelHeight) {
            result = true;
        }
        return result;
    }

    /**
     * Moves snake one step in {@link Direction} specified by {@link Snake#setDirection(Direction)} method. 
     * Default direction is {@link Direction#RIGHT}
     */
    public void moveInDirection() {
        snake.moveInDirection();
        checkIfCircleCaught();
        countDown();
    }

    public UpdateResult update() {
        snake.moveInDirection();
        boolean result = isInBorderCollision();
        if (result) {
            return new UpdateResult(result);
        }
        checkIfCircleCaught();
        countDown();
        return new UpdateResult(true);
    }

    private void checkIfCircleCaught() {
        if (!generator.isCircleCaught()) {
            /* Check if snake caught new circle. If yes, ask circle generator for
             * new circle to be generated and enlarge snake's body with new circle
             */
            if (snake.getX() == generator.getX() && snake.getY() == generator.getY()) {
                generator.circleCaught();
                snake.growSnake(new Circle(Color.RED, Snake.getSnakesCircleSize()));
            }
        }
    }
    /**
     * Sets new {@link Direction} in which snake will be moving.
     * @param direction new direction for snake's movement
     */
    public void setMoveDirection(final Direction direction) {
        snake.setDirection(direction);
    }
    
    public void countDown() {
        generator.countDown();
    }
    
    /**
     * Returns {@link Snake} instance that is managed by this game controller.
     * @return {@link Snake} instance used by this controller
     */
    Snake getSnake() {
        return snake;
    }

}
